package top.lingkang.finalgateway;

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
import top.lingkang.finalgateway.admin.WebApp;
import top.lingkang.finalgateway.config.GatewayConfig;
import top.lingkang.finalgateway.config.RouterConfig;
import top.lingkang.finalgateway.config.TcpConfig;
import top.lingkang.finalgateway.core.NettyService;
import top.lingkang.finalgateway.core.tcp.TcpService;
import top.lingkang.finalgateway.utils.StaticMimes;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/**
 * @author lingkang
 * @create by 2024/4/27 17:10
 */
@Slf4j
public class FinalGateway {
    public static GatewayConfig config;
    public static String dir;
    public static Map<Integer, NettyService> service = new HashMap<>();
    public static Map<Integer, TcpService> tcpService = new HashMap<>();
    public static long startTime = System.currentTimeMillis();

    public static void main(String[] args) {
        dir = System.getProperty("user.dir");
        // 加载 StaticMimes
        StaticMimes.loadConfig();
        WebApp.runWeb(args);
    }

    public static void initService() {
        Runtime.getRuntime().addShutdownHook(new Thread(FinalGateway::shutdownAllService));
        // 启动所有netty服务
        startAllService();
    }

    public synchronized static void startAllService() {
        // 启动netty服务
        for (RouterConfig router : config.getRouterConfigs()) {
            if (!router.isEnable())
                continue;
            NettyService nettyService = new NettyService(router);
            nettyService.start();
            service.put(router.getPort(), nettyService);
        }
        // tcp 服务
        for (TcpConfig tcpConfig : config.getTcpConfigs()) {
            if (!tcpConfig.isEnable())
                continue;
            TcpService ts = new TcpService(tcpConfig);
            ts.start();
            tcpService.put(tcpConfig.getPort(), ts);
        }
    }

    public synchronized static void restartAllService() {
        shutdownAllService();
        ThreadUtil.sleep(3000);
        startAllService();
    }

    public synchronized static void restartService(Integer port) {
        NettyService nettyService = service.get(port);
        nettyService.shutdown();
        service.remove(port);
        ThreadUtil.sleep(2000);
        for (RouterConfig router : config.getRouterConfigs()) {
            if (!router.isEnable())
                continue;
            if (!Objects.equals(port, router.getPort()))
                continue;
            nettyService = new NettyService(router);
            nettyService.start();
            service.put(router.getPort(), nettyService);
            return;
        }
    }

    public synchronized static void shutdownAllService() {
        Iterator<Map.Entry<Integer, NettyService>> iterator = service.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, NettyService> entry = iterator.next();
            entry.getValue().shutdown();
            iterator.remove();
        }

        Iterator<Map.Entry<Integer, TcpService>> tsIterator = tcpService.entrySet().iterator();
        while (tsIterator.hasNext()) {
            Map.Entry<Integer, TcpService> entry = tsIterator.next();
            entry.getValue().shutdown();
            tsIterator.remove();
        }
    }

    public synchronized static void clearIpListCache(Integer port) {
        if (port != null) {
            NettyService nettyService = service.get(port);
            if (nettyService != null)
                nettyService.config.getIpListCheck().clearCache();
            TcpService ts = tcpService.get(port);
            if (ts != null)
                ts.config.getIpListCheck().clearCache();
        } else {
            for (Map.Entry<Integer, NettyService> nettyService : service.entrySet()) {
                nettyService.getValue().config.getIpListCheck().clearCache();
            }
            for (Map.Entry<Integer, TcpService> ts : tcpService.entrySet()) {
                ts.getValue().config.getIpListCheck().clearCache();
            }
        }
    }

    public synchronized static void clearHttpHandlerCache(Integer port) {
        if (port != null) {
            NettyService nettyService = service.get(port);
            if (nettyService != null)
                nettyService.config.getHandlerMap().clear();
        } else {
            for (Map.Entry<Integer, NettyService> nettyService : service.entrySet()) {
                nettyService.getValue().config.getHandlerMap().clear();
            }
        }
    }

    public synchronized static void refreshMonitor() {
        for (Map.Entry<Integer, NettyService> entry : service.entrySet()) {
            entry.getValue().config.getMonitor().refreshToFile();
        }
        for (Map.Entry<Integer, TcpService> entry : tcpService.entrySet()) {
            entry.getValue().config.getMonitor().refreshToFile();
        }
    }
}
